#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>
#include "detail/bmock_expectation.hpp"
#include "detail/bmock_test_control_tools.hpp"
#include <boost/bind.hpp>

namespace bmock {
	static const control_tools_ptr tl(new test_control_tools());
	static const char              func[] = "FUNC1";
	static const func_spec         fs(func,location(__FILE__,__LINE__));
	static const int               val1    = 239;
	static const int               val2    = 563;
	static const int               res     = 133;
	static const int               exp_iv  = 0;
#define ARG_NUM 2
	static	__BMOCK_ARG_LIST(
		ARG_NUM
		,(IN(val1)
		,IN(val1))
		)

	struct sense {
		sense()
			:value_(false)
		{}
		void f() {
			value_ = true;
		}
		operator bool () const {
			return value_;
		}
	private:
		bool value_;
	};

	static void expect(expectation &exp,const int x,const int *y) {
		__BMOCK_ARG_LIST(ARG_NUM,(IN(x),OUT((int *)y)));
		exp.expect_arguments(arg_list(args_,ARG_NUM));
	}

	static result_ptr check(expectation &exp,const int x,int *y) {
		__BMOCK_ARG_LIST(ARG_NUM,(IN(x),OUT(y)))
			return exp.check(fs,arg_list(args_,ARG_NUM));
	}

	BOOST_AUTO_TEST_CASE(test_check_OK) {
		expectation exp(tl);
		sense       s;
		result_ptr  rp;
		bmock_any         av;
		int         iv = exp_iv;
		int         val3 = 0;		

		BOOST_CHECK_NO_THROW(
			exp.expect_call(fs,location(__FILE__,__LINE__));
		expect(exp,val1,&val2); 
		exp.set_result(result_ptr(new value_result(bmock_any(&res)))); 
		exp.connect(boost::bind(&sense::f,&s));
		rp = check(exp,val1,&val3); 
		av = rp->get_value();
		iv = (int)av;
		);	
		BOOST_CHECK(s);
		BOOST_CHECK_EQUAL(res,iv);
		BOOST_CHECK_EQUAL(val2,val3);
	}

	BOOST_AUTO_TEST_CASE(test_calls)
	{
		expectation exp(tl);
		BOOST_CHECK(exp.is_last_call());
		BOOST_CHECK_NO_THROW(exp.expect_call_times_range(8,8));
		BOOST_CHECK(!exp.is_last_call());
	}
}
